home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_08_03 / 8n03028a < prev    next >
Text File  |  1990-03-18  |  5KB  |  186 lines

  1. *****Listing 3*****
  2.  
  3. /* cmd_opts.c, c\lib\src,  (c) 1989 Scott D. Maley
  4. May be freely used, as long as copyright notice is preserved
  5.  
  6. cmd_options(argc, argv, option)
  7.  
  8. int    *argc;        -- pointer to command line arg count
  9. char    *argv[];    -- pointer to array of pointers to 
  10.             command line arguments
  11. struct    options option[]; -- structure array defining valid 
  12.             options
  13.  
  14. This is a function to process command line options (or
  15. switches). The full set of command line arguments is passed
  16. to the routine via argc and argv.  Every option switch
  17. encountered that is a valid match for a switch specified in
  18. the option array is counted, removed from argv, and the
  19. pointer to it's associated value (if any) is moved to
  20. the optv array.  A count of switches which are not valid
  21. matches of any option is returned, and those switches are
  22. left in argv.
  23.  
  24. A switch's value may be contiguous with it, or be separated
  25. from it by white-space (e.g. -svalue, -s value).  White-
  26. space is commonly blanks and tabs, but may also include
  27. commas in some C implementations.  This routine doesn't care.
  28. The C runtime initilization routine which runs before main()
  29. is entered parses the command line into tokens (which the
  30. elements of argv point to), based on it's definition of
  31. white-space.
  32.  
  33. The structure "options" is used to define what this routine
  34. will parse:
  35.  
  36. struct    options
  37. {
  38.     char    s;      -- The option (switch) letter
  39.     int    arg_flg;  -- indicates if an arg is required
  40.     char    **poptv[];-- pointer to option value vector
  41.               -- NULL, if none expected
  42. } ;
  43.  
  44. The third argument to this routine, option, is an array of
  45. the options structures.  The end of this array is signaled
  46. with s == 0.
  47.  
  48. This routine returns:
  49.      0 - if all switches encountered were valid options.
  50.     -n - Negative of the count of invalid (e.g. no
  51.     value followed the switch when one was expected, or
  52.     a value was contiguous     with the switch, but none
  53.     was expected) switches encountered.  N also includes
  54.     a count of switches that were expected, but not
  55.     encountered in argv.
  56.  
  57.     It also sets arg_flg to indicate how many of each
  58.     switch encountered.
  59.  
  60.     
  61.     Sample use:
  62.     ----------
  63.     
  64.     #include <stdio.h>
  65.     #include "cmd_opts.h"
  66.  
  67.     main(argc, argv)
  68.     int    argc;
  69.     char    *argv[];
  70.     {
  71.         char    s, *farg[] *marg[];
  72.         static struct options sw[] =
  73.             {'a', 0, NULL,    -- optional, no value
  74.              'f', 0, &farg,    -- optional, w/ value
  75.              'm', 1, &marg,    -- required, w/ value
  76.                0, 0, NULL};
  77.  
  78.         if (cmd_options( & argc, argv, sw) < 0)
  79.         {
  80.             --- error, handle it here
  81.             ---
  82.         }
  83.         ---
  84.         --- continue with rest of program
  85.         ---
  86.     }
  87.  
  88. *-- History:
  89. * 30 Jan 89 SDM (TASC)        No need to calloc optv, we
  90. *            can work entirely within argv (plus
  91. *            a temp pointer).
  92. * 27 Jan 89 SDM (TASC)        Handle multiple instances
  93. *            of a switch.
  94. *                Retain everything not
  95. *            specified in opts in argv, and set
  96. *            argc accordingly.
  97. * 20 Jan 89 S.D. Maley (TASC)    Initial implementation.
  98. *-- End History
  99. */
  100.  
  101. #include <stdio.h>
  102. #include "cmd_opts.h"
  103.  
  104.  
  105. #define EOS '\0'
  106.  
  107. #define MoveOptFromArg(optv,argv,i,argc) \
  108.    {char *temp;\
  109.     temp= argv[i];\
  110.     RemoveArg(argv,i,argc);\
  111.     (optv)--;\
  112.     optv[0]= temp;\
  113.    }
  114.  
  115. #define RemoveArg(argv,i,argc) \
  116.    {int j;\
  117.     (argc)--;\
  118.     for(j=i;j<argc;j++) argv[j]=argv[j+1];\
  119.    }
  120.  
  121. #define SWFLG '-'
  122. #define SwChr *(argv[i]+1)
  123. #define SwMatch    (*argv[i] == SWFLG && opts[j].s == SwChr)
  124. #define SwValContig (*(argv[i]+2) != EOS)
  125. #define SwValNext (i+1 < *argc && *argv[i+1] != SWFLG)
  126.  
  127.  
  128. cmd_options(argc, argv, opts)
  129.    int     *argc;
  130.    char          *argv[];
  131.    struct options       opts[];
  132. {
  133.    int   i,j, njth, stat;
  134.    char   **optv;      /* equivalent to: *optv[] */
  135.  
  136.    optv = argv + *argc;   /* work from back to front */
  137.  
  138.    /*-- Transfer options from argv to optv
  139.    * -- and check against expectations
  140.    */
  141.    stat = 0;
  142.  
  143.    for (j = 0; opts[j].s != 0; j++)
  144.    {
  145.       njth = 0;
  146.  
  147.       for (i = *argc - 1; i > 0; i--)
  148.       {  /* back to front, we build optv */
  149.          if (SwMatch)
  150.          {
  151.             if (opts[j].poptv == NULL)
  152.             { /* no arg value desired */
  153.                if (SwValContig)
  154.                   continue;   /* next i */
  155.                else
  156.                   RemoveArg(argv,i,*argc);
  157.             } else { /* A value is desired */
  158.                if (SwValContig)
  159.                {
  160.                   argv[i] += 2;   /* past "-'opt_char'" */
  161.                   MoveOptFromArg(optv, argv,i,*argc);
  162.                } else if (SwValNext)
  163.                { /*-- pick up value from next arg */
  164.                   RemoveArg(argv,i,*argc);
  165.                   MoveOptFromArg(optv, argv,i,*argc);
  166.                } else
  167.                   continue;   /* next i */
  168.             }
  169.             njth++;      /* only count valid switches */
  170.          } /* if SwMatch */
  171.       } /* for i */
  172.  
  173.       if (opts[j].poptv != NULL)
  174.          *opts[j].poptv= optv;   /* point to option value vector */
  175.       if (opts[j].arg_flg > njth )
  176.          stat -= opts[j].arg_flg - njth ;  /* not enough */
  177.       opts[j].arg_flg = njth;
  178.  
  179.    } /* for j */
  180.  
  181.    for (i= 1; i < *argc; i++)
  182.       if (*argv[i] == SWFLG)
  183.          stat--;      /* a switch we couldn't handle */
  184.    return(stat);
  185. }
  186.